package de.slothsoft.wasbinich.swingclient.control;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.text.AbstractDocument;

import de.slothsoft.commons.swing.JToolBarManager;
import de.slothsoft.wasbinich.core.GameResult;
import de.slothsoft.wasbinich.core.Picture;
import de.slothsoft.wasbinich.core.WasBinIch;
import de.slothsoft.wasbinich.core.database.Database;
import de.slothsoft.wasbinich.core.database.DatabaseException;
import de.slothsoft.wasbinich.swingclient.WasBinIchSwingClient;
import de.slothsoft.wasbinich.swingclient.common.TimerControl;
import de.slothsoft.wasbinich.swingclient.common.UppercaseDocumentFilter;
import de.slothsoft.wasbinich.swingclient.control.AnswerPanel.OnMover;
import de.slothsoft.wasbinich.swingclient.control.TitlePanel.ScreenSwitcher;
import de.slothsoft.wasbinich.swingclient.res.Images;
import de.slothsoft.wasbinich.swingclient.res.Messages;

public class GamePanel extends ChildPanel implements OnMover {

    private static final long serialVersionUID = -562694750455822666L;

    private static final int LABELS_HEIGHT = 50;
    private static final int BORDER = 5;

    private GameResult gameResult;

    private JPanel basePanel;
    private JComponent questionPanel;
    private AnswerPanel answerPanel;
    private JLabel pictureLabel;
    private JTextField answerTextField;
    private Picture picture;

    private TimerControl timer;

    public GamePanel(ScreenSwitcher screenSwitcher) {
	super(screenSwitcher);
    }

    @Override
    protected Component createControls() {
	this.basePanel = new JPanel();
	this.basePanel.setLayout(new GridBagLayout());
	this.basePanel.setOpaque(false);
	this.questionPanel = createQuestionPanel();
	this.basePanel.add(this.questionPanel, createGridBagConstraints());
	this.answerPanel = createAnswerPanel();
	this.basePanel.add(this.answerPanel, createGridBagConstraints());

	getToolBar().setOpaque(false);

	return this.basePanel;
    }

    private JComponent createQuestionPanel() {
	JPanel panel = new JPanel();
	panel.setOpaque(false);
	panel.setLayout(new BorderLayout());

	JLabel question = new JLabel(Messages.getString("GamePanel.question"));
	question.setFont(new Font(getFont().getFontName(), Font.BOLD, 16));
	question.setOpaque(false);
	question.setHorizontalAlignment(SwingConstants.CENTER);
	panel.add(question, BorderLayout.NORTH);

	this.pictureLabel = new JLabel();
	this.pictureLabel.setBorder(BorderFactory.createEmptyBorder(BORDER, 0, BORDER, 0));
	panel.add(this.pictureLabel, BorderLayout.CENTER);

	this.answerTextField = new JTextField();
	((AbstractDocument) this.answerTextField.getDocument()).setDocumentFilter(new UppercaseDocumentFilter());
	this.answerTextField.addKeyListener(new KeyAdapter() {
	    @Override
	    public void keyReleased(KeyEvent e) {
		if (e.getKeyCode() == KeyEvent.VK_ENTER) {
		    performAnswerEntered();
		}
	    }
	});
	panel.add(this.answerTextField, BorderLayout.SOUTH);

	return panel;
    }

    protected void performAnswerEntered() {
	String answer = this.answerTextField.getText();
	if (answer != null && !answer.isEmpty()) {
	    this.questionPanel.setVisible(false);
	    this.answerPanel.setVisible(true);
	    this.answerPanel.setSize(this.basePanel.getSize());

	    this.answerPanel.calculateAnswer(this.picture, answer, (ImageIcon) this.pictureLabel.getIcon(),
		    this.gameResult);
	}
    }

    private AnswerPanel createAnswerPanel() {
	return new AnswerPanel(this);
    }

    @Override
    public void moveOn() {
	this.questionPanel.setVisible(true);
	this.answerPanel.setVisible(false);
	showPanel();
    }

    @Override
    public void showPanel() {
	this.questionPanel.setVisible(true);
	this.answerPanel.setVisible(false);

	try {
	    this.picture = Database.getInstance().getPictureBean().getRandomPicture();
	} catch (DatabaseException e) {
	    WasBinIchSwingClient.handleFatalException(e);
	    return;
	}

	this.pictureLabel.setIcon(Images.getPictureFromData(this.picture.section, getImageResizeDimension()));
	this.pictureLabel.getParent().doLayout();

	this.answerTextField.setText(null);
	this.answerTextField.requestFocus();

	WasBinIchSwingClient.getMainPanel().doLayout();
	WasBinIchSwingClient.getMainPanel().repaint();
    }

    private Dimension getImageResizeDimension() {
	Dimension resizeDimension = this.basePanel.getSize();
	resizeDimension.width = Math.min(resizeDimension.height - LABELS_HEIGHT, resizeDimension.width);
	resizeDimension.height = resizeDimension.width;
	return resizeDimension;
    }

    private GridBagConstraints createGridBagConstraints() {
	return new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.CENTER,
		new Insets(0, 0, 0, 0), 0, 0);
    }

    @Override
    protected void fillToolbar(JToolBarManager manager) {
	super.fillToolbar(manager);
	manager.addSeparator();
	this.timer = TimerControl.createCountDown(WasBinIch.GAME_LENGTH_IN_SECONDS + 1);
	this.timer.getTimer().setDelay(TimerControl.TIME_SECOND);
	this.timer.addActionListener(new ActionListener() {

	    @Override
	    public void actionPerformed(ActionEvent e) {
		endGame();
	    }
	});
	manager.getToolBar().add(this.timer);
    }

    public void startGame() {
	this.gameResult = new GameResult();
	this.timer.start();
    }

    public void quietlyEndGame() {
	this.timer.stop();
    }

    protected void endGame() {
	GameResultPanel gameResultPanel = (GameResultPanel) getScreenSwitcher().switchScreen(
		MainPanel.SCREEN_GAME_RESULT);
	gameResultPanel.showResult(this.gameResult);
    }
}
